using System;
using System.Collections.Generic;
using TestCases.CompareAssert.Core;
using TestCases.CompareAssert.Core.Comparers.Interfaces;
using TestCases.CompareAssert.Core.Compositions;
using TestCases.CompareAssert.Core.Interfaces;
using TestCases.Tests.CompareAssert.Builders;
using TestCases.Utils.Pairs;

namespace TestCases.Tests.Helpers
{
    public class TestBuilderFactory: IResultBuilderFactory
    {
        private readonly IObjectComparer _testComparer;
        
        private readonly IList<IPair<string, object>> _expectedTemplates;
        private int _lastTest;

        public TestBuilderFactory(IObjectComparer testComparer, IList<IPair<string, object>> expectedTemplates)
        {
            _testComparer = testComparer;
            _expectedTemplates = expectedTemplates;
        }
        
        private IResultBuilder CreateBuilder(CompareResult result)
        {
            if (ReferenceEquals(result.Comparer, _testComparer) &&
                _expectedTemplates != null && 
                _lastTest < _expectedTemplates.Count)
            {
                var pair = _expectedTemplates[_lastTest++];
                return new TestResultBuilder(result)
                {
                    ExpectedTemplate = pair.Left,
                    ExpectedArgs = pair.Right
                };
            }
            return ResultBuilderTest.NewBuilder(result);
        }

        public IResultBuilder ForSimpleResult(IObjectComparer comparer, CompareStatus status, IPair<IComparerObject, IComparerObject> pair)
        {
            return CreateBuilder(new CompareResult(comparer, status, pair));
        }

        public IResultBuilder ForDecoratorResult(IObjectComparer comparer, CompareStatus status, IPair<IComparerObject, IComparerObject> pair, IResultProvider child)
        {
            return CreateBuilder(new CompareResult(comparer, status, pair, child.GetResult()));
        }

        public IResultBuilder ForCompositeResult<T>(IObjectComparer comparer, CompareStatus status, IPair<IComparerObject, IComparerObject> pair, IList<T> children) where T: IResultProvider
        {
            return CreateBuilder(new CompareResult(comparer, status, pair, children.GetResults()));
        }

    }
}